/*
* @Author: fanjs
* @Date: 2024-03-21 16:02:00
* @Description: 记账管理 API
*/
import { api, auth } from '@core/decorator'
import BillModel from '@app/model/bill'
import RecordModel from '@app/model/record'
import { AuthRouterContext } from 'router'
import { DateUtil } from '@core/util'
@api.controller('/v1/record')
class RecordController {
  /**
   * 获取操作记录列表
   * @param billId 账单ID
   * @param page 页码
   * @param pageSize 每页数量
   */
  @api.post('/list')
  @api.auth('UserScope')
  @auth.login_required
  async getRecordList(ctx: AuthRouterContext) {
    const { billId, page = 1, pageSize = 10 } = ctx.request.body as any

    if (!billId) throw new global.errs.ParameterException('账单ID不能为空')

    const result = await RecordModel.getRecordList(Number(billId), {
      page: Number(page),
      pageSize: Number(pageSize)
    })

    throw new global.errs.Success(result)
  }

  /**
   * 创建操作记录 - 出入账
   * @param billId 账单ID
   * @param hasMoneyType 是否记录金额类型
   * @param moneyType 金额类型：本金、利息
   * @param amount 操作金额
   * @param remark 备注
   */
  @api.post('/create/:billId')
  @api.auth('UserScope')
  @auth.login_required
  async createIncome(ctx: AuthRouterContext) {
    const { uid, nickname } = ctx.auth
    const { billId } = ctx.params
    const { needMoneyType, moneyType, amount, remark } = ctx.request.body as any

    if (!amount) throw new global.errs.ParameterException('请填写金额')

    // 获取账单信息（直接获取 Sequelize 模型实例）
    const billInstance = await BillModel.getBillById(Number(billId))
    if (!billInstance) throw new global.errs.NotFound('账单不存在')
    
    const bill = billInstance.toJSON()
    const billType = bill.type

    // 记录操作前的数据
    const beforePrincipal = Number(bill.principal) // 账单剩余本金
    const beforeInterest = Number(bill.remainingInterest) // 账单剩余利息
    const beforeTotalInterest = Number(bill.totalInterest) // 账单总利息
    
    // 校验操作金额
    if (needMoneyType) {
      if (!moneyType) throw new global.errs.ParameterException('请选择金额类型')
      if (moneyType === 'principal' && amount > beforePrincipal) throw new global.errs.ParameterException('操作金额不能大于本金')
      if (moneyType === 'interest' && amount > beforeInterest) throw new global.errs.ParameterException('操作金额不能大于利息')
    }
    
    const lastInterestDate = BillModel.calculateLastInterestDate(bill.nextDate, bill.rateType) // 上一个计息日期
    const count = RecordModel.calculateCount(lastInterestDate, new Date(), bill.rateType) // 计算计息次数
    const currentInterest = RecordModel.calculateInterest(bill.rate, beforePrincipal, count) // 根据次数计算本次利息
    
    let afterPrincipal = beforePrincipal // 本金
    let afterInterest = beforeInterest + currentInterest // 利息
    let nextInterest = bill.nextInterest // 下周期利息
    let nextDate = bill.nextDate // 下周期日期

    /** 是否需要重新计算利息 */
    const needCalculateInterest = !needMoneyType || moneyType === 'principal'

    switch (billType) {
      case 'save':
        // 存款类型 （取款 计息）（取息 不计息）
        if (needMoneyType) {
          if (moneyType === 'interest') afterInterest = beforeInterest - amount
          if (moneyType === 'principal') afterPrincipal = beforePrincipal - amount
        } else {
          // 追加存入 计息
          afterPrincipal = beforePrincipal + amount
        }
        break
      case 'borrow':
        // 借款类型 （还款 计息）（还息 不计息）
        if (needMoneyType) {
          if (moneyType === 'interest') afterInterest = beforeInterest - amount
          if (moneyType === 'principal') afterPrincipal = beforePrincipal - amount
        } else {
          // 追加借款 计息
          afterPrincipal = beforePrincipal + amount
        }
        break
      default:
        throw new global.errs.ParameterException('账单类型错误')
    }

    // 重新计算下期利息 及 日期
    if (needCalculateInterest) {
      nextInterest = RecordModel.calculateInterest(bill.rate, afterPrincipal, 1)
      nextDate = DateUtil.formatDate(DateUtil.addMonthsOrDays(DateUtil.getCurrentDateTime(), 1, bill.rateType === 'M' ? 'month' : 'day'))
    }

    /** 创建一条操作记录 */ 
    await RecordModel.createRecord({
      billId: Number(billId),
      billType,
      needMoneyType,
      moneyType,
      amount,
      beforePrincipal,
      afterPrincipal,
      beforeInterest,
      afterInterest,
      operator: uid.toString(),
      operatorName: nickname || '',
      remark
    })

    /** 
     * 更新账单数据
     * 1. 本金
     * 2. 利息总额
     * 3. 剩余利息
     * 4. 下周期利息
     * 5. 计息周期
     * 6. 记录操作
     * 7. 是否结清
     * 8. 已取|还本金
     * 9. 已取|还利息
     * 10. 追加|存本金
    */
    const updateData: any = {
      principal: Number(afterPrincipal),
      totalInterest: Number(beforeTotalInterest + currentInterest),
      remainingInterest: Number(afterInterest),
      nextInterest: Number(nextInterest),
      nextDate,
      hasRecord: true, // 记录操作
    }

    /** 根据操作类型更新不同的本金和利息字段 */
    if (needMoneyType) {
      if (moneyType === 'principal') updateData.settledPrincipal = Number(bill.settledPrincipal || 0) + Number(amount) // 已操作本金（取款/还款）
      if (moneyType === 'interest') updateData.settledInterest = Number(bill.settledInterest || 0) + Number(amount) // 已操作利息（取息/还息）
    } else {
      updateData.additionalPrincipal = Number(bill.additionalPrincipal || 0) + Number(amount) // 追加操作（追存/追借）
    }

    /** 是否结清（剩余本金 <= 0 && 剩余利息 <= 0） */
    updateData.isSettled = Number(bill.principal) <= 0 && Number(bill.remainingInterest) <= 0

    await billInstance.update(updateData)
    
    throw new global.errs.Success(true)
  }
}